"""Filter a beaker xml job to contain recipeSet of specific test id."""
import argparse
import os
import sys
import xml.etree.ElementTree as ET

from cki_lib import misc
from cki_lib.logger import get_logger
import sentry_sdk

LOGGER = get_logger('cki.cki_tools.filter_bkr_task')


# For multihost jobs we need to keep the whole recipeSet and not only a recipe
def recipeset_task_index(recipe_set, test_id):
    """
    Check if a recipe in the recipeSet contains test id.

    If found test id it will return its index in the task list,
    if test id is not found it returns -1.
    """
    for recipe in recipe_set.findall('recipe'):
        for task_index, task in enumerate(recipe.findall('task')):
            for param in task.findall('.//param'):
                if (param.get('name') == "CKI_ID" and
                   param.get('value') == str(test_id)):
                    return task_index
    # didn't find the task
    return -1


class BeakerXML:
    """
    Parses beaker xml.

    Class to parse a beaker xml to include only recipeSet that contains
    specific test id.
    """

    bkr_xml = None
    tree = None
    root = None

    def load_xml(self, path):
        """Load xml file."""
        self.tree = ET.parse(path)
        self.root = self.tree.getroot()
        # remove any group specific that was set, like cki...
        self.root.attrib['group'] = ''

    def filter_task(self, test_id):
        """
        Remove tasks not related to test id.

        Remove from the xml all recipes sets that don't contain test id
        to be able to handle multihost tests if a recipet set contains a recipe
        that has a task with correct test id, it should keep  all recipes
        from the recipeSet. The tasks from the recipes after the ones related
        to the test id are removed.
        """
        if not self.root:
            LOGGER.error("Beaker xml is not loaded")
            return False
        for recipe_set in self.root.findall('recipeSet'):
            task_index = recipeset_task_index(recipe_set, test_id)
            if task_index == -1:
                self.root.remove(recipe_set)
                continue
            # For multihost the related tasks have the same index
            for recipe in recipe_set.findall('recipe'):
                for index, task in enumerate(recipe.findall('task')):
                    # after task is found, every other task can be removed
                    if index > task_index:
                        recipe.remove(task)
        # if there is no recipe in the recipeSet remove it
        if not self.root.findall('recipeSet'):
            LOGGER.error("Didn't find any test with test id %s", test_id)
            return False
        return True

    def save_xml(self, output_file):
        """Print xml."""
        os.makedirs(os.path.dirname(output_file), exist_ok=True)
        self.tree.write(output_file, encoding='utf8')


def main(args=None):
    """Run the script as cli."""
    parser = argparse.ArgumentParser()
    parser.add_argument("--beaker-xml-path", dest="input_xml", required=True,
                        help="beaker xml file")
    parser.add_argument("--output-xml", dest="output_xml", required=True,
                        help="filtered beaker xml file")
    parser.add_argument("--test-id", "-t", required=True, type=int, help="CKI test id")
    parsed_args = parser.parse_args(args)

    bkr_class = BeakerXML()
    bkr_class.load_xml(parsed_args.input_xml)
    if not bkr_class.filter_task(parsed_args.test_id):
        return 1
    bkr_class.save_xml(parsed_args.output_xml)
    return 0


if __name__ == '__main__':  # pragma: no cover
    misc.sentry_init(sentry_sdk)
    sys.exit(main(sys.argv[1:]))
